﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;
using System.Windows.Forms.DataVisualization.Charting;


namespace FastGraphClustering_13._12
{
    public partial class Main_Window : Form
    {

        string graclusFolder = Directory.GetCurrentDirectory() + "\\graclus",DefaultKernelMatrix, Orignalpercent;        
        int MinNodesPerCluster, MinEdgesPerCluster, MinEdgesPercentPerCluster;
        int DefaultSigma, MaxClustersRequested;
        int  GraclusNumOfClusters, MinLocalSearchDefault;        
        int m_NumOfClusterKernel_flag = 1, m_KernrlMatrix_flag = 1, m_sigmaFlag = 1, ChooseMatrix = 0, timerindex = 0;
        int historyNetwork_flag = 0, historyMatrix_flag = 0, m_currentNetworkIndex = -1, sigmaDotEntered_flag = 0, sigmaError_flag = 0, indexOfTheDot_sigma = 0;
        int OriginalNetworkNumOfNodes = 0, CurrentNumberOfClusters = 0, ChoosenNumOfClusters = 0, ReplacedClusterIndex = -1,PreviousNumOfClusters=-1;
        int numOfClustersAfterKernel = 0, LengthOfSigma = 0;
        Network m_Current_Network, m_Network1, DichotomNetwork;
        protected Bitmap m_bmpGraph1, m_bmpGraph3, m_bmpGraph3_Graclus, m_bmpHistorySmall, m_bmpHistorySmall_Graclus;
        protected Bitmap m_bmpGraph4, m_bmpGraph5, m_bmpHistoryBig,m_bmpHistoryMedium;
        Graphics m_gImage1, m_gImage3, m_gImage3_Graclus;
        Graphics m_gImage4, m_gImage5;
        Error_Msg error = new Error_Msg();  Success_msg successMSG;
        GeneralMsg general_error = new GeneralMsg();
        Average_graph GraphGraclus;
        Kernel_K_Means m_Kernel_K_Means,DichotomKernel_K_Means,UpdatedKernel_K_Means, PreviousKernel_K_Means;
        Kernel_K_Means Graclus_K_Means;
        Cluster[] PreviousClusters;
        infoWindow info=new infoWindow();
        Point[] nodes1;
        static public int imgXClusteredGraph = 750, imgYClusteredGraph = 534, calcPosFlag = 1, kernelFlag, MaxNumOfClustersPossible = 100;
        Icon [] icon_Array;        
        double sigma=0, SumOfNodes = 0;
        public int Test2_flag = 0, Test1_flag = 0;
        public Information NetInfo_Window;
        int[] history = new int[4], LastClusterNode;        
        char[] charArrForSigma=new char[20];        
        static public int testFlag = 0;
        static public int NodesInKernel = 0;
        System.Windows.Forms.CheckBox[] SelectBox2;
        Timer GlowTimer;
        Boolean manualDisableSelectAll = false, AutomaticDichotom = false, ContinueDichotom = true, Graclus_Clustered_Flag = false, Dichotom_Clustered_Flag = false;
        ArrayList Graclus_Best9, Graclus_Rest_Of9 ,Dichotom_Best9,Dichotm_Rest_Of9;
        

        public Main_Window()
        {
            setConstants();
            InitializeComponent();
            m_bmpGraph1 = new Bitmap(1180, 670);// initial unclustered network            
            m_bmpGraph3 = new Bitmap(imgXClusteredGraph, imgYClusteredGraph);// clustered Dichotom
            m_bmpGraph3_Graclus = new Bitmap(imgXClusteredGraph, imgYClusteredGraph);//Graclus Cluster
            m_bmpGraph4 = new Bitmap(578, 348);//  graclus results tab
            m_bmpGraph5 = new Bitmap(578, 348);//  Dichotom results tab
            m_bmpHistorySmall = new Bitmap(259,281);
            m_bmpHistoryBig = new Bitmap(1260,660);// first 2 images the bigger 
            m_bmpHistoryMedium=new Bitmap(300,218);

            m_gImage1 = Graphics.FromImage(m_bmpGraph1);// initial unclustered network
            m_gImage3 = Graphics.FromImage(m_bmpGraph3);// clustered Dichotom
            m_gImage3_Graclus = Graphics.FromImage(m_bmpGraph3_Graclus);//Graclus Cluster
            m_gImage4 = Graphics.FromImage(m_bmpGraph4);//  graclus results tab
            m_gImage5 = Graphics.FromImage(m_bmpGraph5);//  Dichotom results tab

            icon_Array =new Icon [50];
            for (int h = 0; h < 5; h++)
            {
                icon_Array[h*10 + 0] = new Icon("icons\\1.ico");
                icon_Array[h * 10 + 1] = new Icon("icons\\2.ico");
                icon_Array[h * 10 + 2] = new Icon("icons\\3.ico");
                icon_Array[h * 10 + 3] = new Icon("icons\\4.ico");
                icon_Array[h * 10 + 4] = new Icon("icons\\5.ico");
                icon_Array[h * 10 + 5] = new Icon("icons\\6.ico");
                icon_Array[h * 10 + 6] = new Icon("icons\\7.ico");
                icon_Array[h * 10 + 7] = new Icon("icons\\8.ico");
                icon_Array[h * 10 + 8] = new Icon("icons\\9.ico");
                icon_Array[h * 10 + 9] = new Icon("icons\\10.ico");
            }              

               this.NetworkInformation_groupBox.Visible = false;
               for (int i = 0; i < 4; i++)// initialize the history array to -1 so incase there is les then 5 steps we will know
                   history[i] = -1;

               LoadNetworkInfo();
               GlowTimer = new Timer();
               GlowTimer.Interval = 500;
               GlowTimer.Tick += new EventHandler(GlowTimer_Tick);

               Graclus_Rest_Of9 = new ArrayList();
               Dichotm_Rest_Of9 = new ArrayList();

               InitializeChartAreas();
        }

        
        void setConstants()
        {
            MinNodesPerCluster = 10;
            MinEdgesPerCluster = 5;
            MinEdgesPercentPerCluster = 20;           
            DefaultKernelMatrix = "Ratio Association";
            MaxClustersRequested = 30;
            DefaultSigma = 2;
            MinLocalSearchDefault = 10;
        }
        private void LoadNetworkInfo()
        {
            try
            {   using (StreamReader sr = new StreamReader("Networks\\networkInfo.txt"))
                {
                    string line;                                       
                    char[] seps = new char[] { ' ' };                    
                    while ((line = sr.ReadLine()) != null)
                    {                        
                        string[] str1 = line.Split(' ');                                             
                        ListViewItem NetListViewItem = new ListViewItem(str1[0]);    // net ID                        
                        NetListViewItem.SubItems.Add(str1[1]);      // Nodes#
                        int nodesnum = Convert.ToInt32(str1[1]);     // Nodes# to str
                        int edgesnum = Convert.ToInt32(str1[2]);    // Edges# to str
                        float fullgraphedges = ((nodesnum * (nodesnum - 1)) / 2);
                        float Percent = (edgesnum / fullgraphedges) * 100;
                        int intpercent = Convert.ToInt32(Percent);
                        string percentint = (Convert.ToString(intpercent) + "%");
                        NetListViewItem.SubItems.Add(percentint);     // Edges% (amount) // full graph (n*(n-1))/2
                        NetworkListView.Items.Add(NetListViewItem);
                    }
                }// End using sr               
                NetworkListView.EndUpdate();
                NetworkListView.Refresh();
                graclusRunButton.Enabled = false;
                Dichotom_button.Enabled = false;
                Run_K_Means_button.Enabled = false;
            }catch (Exception e)            
            {                
                Console.WriteLine("The file could not be read:");
                Console.WriteLine(e.Message);
            }
        }


        private void NetworkListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.graphRepresntation_panel.Visible = false;
            if (NetworkListView.SelectedItems.Count == 0) 
                return;
            string selectedstr = NetworkListView.SelectedItems[0].SubItems[0].Text; //get selected network           
            Orignalpercent = NetworkListView.SelectedItems[0].SubItems[2].Text; // get selected network edge percent
            Orignalpercent=Orignalpercent.Remove(Orignalpercent.Length - 1, 1);
            int temp = Convert.ToInt32(selectedstr);
            m_currentNetworkIndex = temp;
            int NumOfNodes = 0;
            m_Network1 = new Network("Networks\\" + selectedstr + "-dichotom.txt");
            m_Network1.get_numOfNodes(ref NumOfNodes);
            m_Current_Network = m_Network1; 
            this.ConvertNetwork_Button.Enabled = true;
            this.Run_K_Means_button.Enabled = false;
            this.Dichotom_button.Enabled = false;
            this.graclusRunButton.Enabled = false;
        }


// Creates a bmp randomized graph from txt and paint it
        private void ConvertNetwork_Button_Click(object sender, EventArgs e)
        {
            int i = 0; 
            this.graphRepresntation_panel.Visible = true;
            Draw_Network(); // prepare m_gImage1 - original network graph
            this.m_Current_Network.get_numOfNodes(ref i);   // ref i  is like a pointer- to return value in
            OriginalNetworkNumOfNodes = i;
            ClearDataFunc();        // clear all tabs results and reset buttons and imgs
            saveBmp(1, m_bmpGraph1, m_bmpHistoryBig, 805   , 485); // save original network to image            
            // prepare kernel matrix for next tab ( only because the old alg worked with smaller network initially)
            int temp = 0;
            this.m_Current_Network.get_numOfNodes(ref temp);
            m_Current_Network.Calc_adjacnyKernel(temp, temp);
            graclusRunButton.Enabled = true;
            Dichotom_button.Enabled = true;
            Run_K_Means_button.Enabled = true;
        }


// saves bmp files of current status of clustering - according to index - need to clean some cased from old project
        private void saveBmp(int index, Bitmap Original_bmp, Bitmap new_bmp, int new_width, int new_hight)
        {/*
            int chosenNetwork = m_currentNetworkIndex;
            new_bmp = ResizeBitmap(Original_bmp, new_width, new_hight);
            switch (index)
            {
                case 1:// save the original network
                    new_bmp.Save("bmp\\Original_Unclustered_Network" + chosenNetwork + ".bmp");
                    break;
                case 2://save clustered network
                    new_bmp.Save("bmp\\Network" + chosenNetwork + "_matrix" + ChooseMatrix + "_clustered_network.bmp");
                    break;
                case 3://save clustered core
                    new_bmp.Save("bmp\\Network" + chosenNetwork + "_matrix" + ChooseMatrix + "_initial_clustered_core.bmp");
                    break;
                case 4://save step1
                    new_bmp.Save("bmp\\Network" + chosenNetwork + "_matrix" + ChooseMatrix + "_step1.bmp");
                    break;
                case 5://save step2
                    new_bmp.Save("bmp\\Network" + chosenNetwork + "_matrix" + ChooseMatrix + "_step2.bmp");
                    break;
                case 6://save step3
                    new_bmp.Save("bmp\\Network" + chosenNetwork + "_matrix" + ChooseMatrix + "_step3.bmp");
                    break;
            }
            if (index != 1 && index != 2)   
                history[index - 3] = m_Current_Network.numOfNodesKernel_new;
        */
        }

        
        private void KernellMatrix_comboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (KernelMatrix_comboBox.SelectedIndex == 0)
                m_KernrlMatrix_flag = 0;
            else
            {
                ChooseMatrix = KernelMatrix_comboBox.SelectedIndex;
                m_KernrlMatrix_flag = 1;
                this.Online_Clustering_panel.Visible = false;
            }
        }

        private void NumOfClusterKernel_comboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
              this.m_gImage3.Clear(Color.Transparent);
              ChoosenNumOfClusters = 9;// NumOfClusterKernel_comboBox.SelectedIndex; 
            m_NumOfClusterKernel_flag = 1;
            this.Online_Clustering_panel.Visible = false;
        }


        /* running examples of graclus CLI :
         graclus -o rassoc -b mygraph 100      <--- 100 clusters, ratio association, no local search, only cluster using boundary points
        graclus -o ncut -l 20 mygraph 100  */
        private void graclusRunButton_Click(object sender, EventArgs e)
        {
            int GraclusLocalSearch,currentClusterTry=-1;
            Boolean TryAgainFlag = true;
            GraclusNumOfClusters = this.graclusClusternumCombobox.SelectedIndex+1;   
            if (!graclusLocalSearchCheckbox.Checked)
                GraclusLocalSearch = Convert.ToInt32(GraclusLocalSearchTextbox.Text);
            string GraclusKernelMatrix = this.graclusKernelCombobox.SelectedItem as string;
            int GraclusChosenMatrix=this.graclusKernelCombobox.SelectedIndex;
            if (GraclusKernelMatrix == "Ratio Association")
                GraclusKernelMatrix = "rassoc";
            else if (GraclusKernelMatrix == "Normalized Cut")
                GraclusKernelMatrix = "ncut";
            string networkChosen = Convert.ToString(m_currentNetworkIndex);
            string[] Commands = new String[10];
            while (TryAgainFlag)     // if CMDRunProc Failes, Try again with another cluster number
            {
                currentClusterTry++;
                if (GraclusNumOfClusters + currentClusterTry > 30 && currentClusterTry < 5)
                    GraclusNumOfClusters -= 10; // try lower cluster numbers

                Commands[currentClusterTry] = "graclus.exe -o " + GraclusKernelMatrix;
                if (graclusLocalSearchCheckbox.Checked == true)
                    Commands[currentClusterTry] += " -l " + GraclusLocalSearchTextbox.Text;
                Commands[currentClusterTry] += " " + networkChosen + "-graclus.txt "; // network number
                Commands[currentClusterTry] += Convert.ToString(GraclusNumOfClusters + currentClusterTry);
                if (CMDRunProc(Commands[currentClusterTry], networkChosen, GraclusNumOfClusters + currentClusterTry) == true)
                    TryAgainFlag = false;   // CMDRunProc Success ! Stop While
                else
                {
                    Success_msg suc = new Success_msg();
                    suc.label1.Text = "Algorithm Optimized Cluster number : "+(GraclusNumOfClusters + currentClusterTry);
                    suc.label1.Text += "\n     and Clustered the Graph again";
                    suc.label2.Visible = false;
                    suc.Visible = true;
                    suc.Refresh();
                }
            } 
            GraclusNumOfClusters = GraclusNumOfClusters + currentClusterTry;            
            // Fetch results, Evaluate and Sort :
            Graclus_K_Means = SetGraclusResults(GraclusNumOfClusters, GraclusChosenMatrix);
            EvaluateClusteringQuality(Graclus_K_Means, GraclusNumOfClusters);            
            Graclus_Best9=SortBestClusters(Graclus_K_Means, GraclusNumOfClusters, ref Graclus_Rest_Of9);
            Graclus_Clustered_Flag = true;
            //Draw results image :
            m_gImage3_Graclus.Clear(Color.Transparent);
            Draw_Clusterd_Kernel(m_gImage3_Graclus, Graclus_K_Means, GraclusNumOfClusters,true);
            saveBmp(3, m_bmpGraph3_Graclus, m_bmpHistorySmall_Graclus, 259, 218);            
            // Update Table data:
            FillTable(ref Graclus_dataGridView1, Graclus_K_Means, GraclusNumOfClusters,true);                        
            FillGraph(ref this.chart2);      // results tab 

            Graclus_NetworkInformation_groupBox.Refresh();            
            Online_Clustering_groupBox.Refresh();    
            this.Graclus_Clustering_panel.Refresh();
            GraclusRadiobutton_CheckedChanged( sender,  e);
            this.Clear_data.Enabled = true;    // enable "Clear" button    
        }        


        // Dichotom 1st Clustering :  use m_Kernel_K_Means with 2 clusters 
        private void Dichotom_button_Click(object sender, EventArgs e)
        {
            Error_Msg2 err; //check Input errors :
            CurrentNumberOfClusters = ChoosenNumOfClusters = 2;
            if (m_sigmaFlag == 0 || m_KernrlMatrix_flag == 0)
            {
                err = new Error_Msg2();
                err.label1.Text = "Select Clustering Preferences";
                err.label2.Visible = false;
                err.Visible = true;
            }
            else
            {
                m_Kernel_K_Means = CreateRunK_Means(m_Current_Network); // Run algoritm in m_Kernel_K_Means - 1st cluster intance
                if (m_Kernel_K_Means!=null && m_Kernel_K_Means.ErrorFlag!=1)
                {
                    UpdatedKernel_K_Means = m_Kernel_K_Means;  // Set Current K_Means
                    CurrentNumberOfClusters = m_Kernel_K_Means.ClusterArrayActualLength;
                    this.NetworkInformation_groupBox.Visible = true;

                    Dichotom_Clustered_Flag = true; 
                    EvaluateClusteringQuality(UpdatedKernel_K_Means, CurrentNumberOfClusters);
                    Dichotom_Best9 = SortBestClusters(UpdatedKernel_K_Means, CurrentNumberOfClusters, ref Dichotm_Rest_Of9);
                    Draw_Clusterd_Kernel(m_gImage3, m_Kernel_K_Means, CurrentNumberOfClusters,false);
                    saveBmp(3, m_bmpGraph3, m_bmpHistorySmall, 259, 218);
                    InjectChartGraph_ResetGui(UpdatedKernel_K_Means, CurrentNumberOfClusters);
                    NetworkInformation_groupBox.Refresh();
                    Online_Clustering_groupBox.Refresh();
                    this.Clear_data.Enabled = true;    // enable "Clear" button
                }
            }
            if (AutomaticDichotom)
                ReClusterButton_Click(sender, e);
        }


        // Re Cluster an existing cluster (Dichotom)
        private void ReClusterButton_Click(object sender, EventArgs e)
        {
            Boolean manualRecluster=true;
            if (sender == Dichotom_button)
                manualRecluster = false;   
            else AutomaticDichotom = false;

            while (ContinueDichotom)
            {
                ContinueDichotom = false;
                string str = ""; int numofnodesIntxt = 0; Boolean Errorflag = false;
                int RecentNumberOfClusters = CurrentNumberOfClusters;
                Boolean ChangeFlag = false, ClusterableFlag = false, ClusterSelected = false;
                if (!manualRecluster)
                    SelectAllbox.Checked = true;
                for (int k = 0; k < RecentNumberOfClusters; k++)
                {
                    if (SelectBox2[k].Checked && (ClusterableFlag = IsClusterable(k, ref str, UpdatedKernel_K_Means)))    // check which clusters needed to ReCluster
                    {
                        ClusterSelected = true;
                        if (!ChangeFlag)    // make only one backup (Before 1st changes made)
                        {
                            PreviousClusters = BackupClusterAndClusterNode(ref LastClusterNode, UpdatedKernel_K_Means);
                            ChangeFlag = true; // Mark Backup                            
                        }
                        ContinueDichotom = true;
                        this.K_Means_progressBar.Value = K_Means_progressBar.Minimum;
                        DichotomNetwork = PullClusterFromNetworkToTXT(k, ref numofnodesIntxt, UpdatedKernel_K_Means); // Pull Cluster k From Network to new Network Object
                        // Prepare K_Means & Run it, Then Update Results & Gui                      
                        DichotomKernel_K_Means = CreateRunK_Means(DichotomNetwork); // Create & Run K_means for new cluster procces
                        if (DichotomKernel_K_Means != null && DichotomKernel_K_Means.ErrorFlag != 1)
                        {
                            PreviousKernel_K_Means = UpdatedKernel_K_Means; //backup current K_Means to Previous K_Means before editing
                            ReplacedClusterIndex = k; // save original cluster number (for backup)  
                            InjectNewClusterToResults(0, CurrentNumberOfClusters, k, numofnodesIntxt);
                            InjectNewClusterToResults(1, ReplacedClusterIndex, k, numofnodesIntxt);
                            CurrentNumberOfClusters++; // Update New Number of Total Clusters   
                            UpdatedKernel_K_Means.ClusterArrayActualLength++;
                            
                        }
                        else Errorflag = true;
                    }
                }
                if (ChangeFlag)
                {
                    m_gImage3.Clear(Color.Transparent);
                    EvaluateClusteringQuality(UpdatedKernel_K_Means, CurrentNumberOfClusters);
                    Dichotom_Best9 = SortBestClusters(UpdatedKernel_K_Means, CurrentNumberOfClusters, ref Dichotm_Rest_Of9);
                    Dichotom_Clustered_Flag = true;
                    Draw_Clusterd_Kernel(m_gImage3, UpdatedKernel_K_Means, CurrentNumberOfClusters, false);
                    saveBmp(3, m_bmpGraph3, m_bmpHistorySmall, 259, 218);
                    InjectChartGraph_ResetGui(UpdatedKernel_K_Means, CurrentNumberOfClusters);
                    NetworkInformation_groupBox.Refresh();
                    Online_Clustering_groupBox.Refresh();
                    GlowTimer.Enabled = true;
                }
                else if (!ClusterSelected)
                    str += "\nPlease Select a Cluster...\n";
                if (manualRecluster && (!ClusterableFlag || !ChangeFlag) )
                {
                    successMSG = new Success_msg();
                    successMSG.label1.Text = str;
                    successMSG.label2.Visible = false;
                    successMSG.Visible = true;
                }
                if (manualRecluster)
                    ContinueDichotom = false;
            }
            ContinueDichotom = true;            
            SelectAllbox.Checked = false;
        }


        // old algorithm - regular Kernel k-means
        private void Run_K_Means_button_Click(object sender, EventArgs e)
        {
            Error_Msg2 err; //check Input errors :
            if (m_sigmaFlag == 0 || m_KernrlMatrix_flag == 0 || m_NumOfClusterKernel_flag == 0)
            {
                err = new Error_Msg2();
                err.label1.Text = "Select Clustering Preferences";
                err.label2.Visible = false;
                err.Visible = true;
            }
            else
            {
                CurrentNumberOfClusters = ChoosenNumOfClusters = 9;//NumOfClusterKernel_comboBox.SelectedIndex;
                m_Kernel_K_Means = CreateRunK_Means(m_Current_Network); // m_Kernel_K_Means - 1st cluster intance
                if (m_Kernel_K_Means != null && m_Kernel_K_Means.ErrorFlag != 1)
                {
                    UpdatedKernel_K_Means = m_Kernel_K_Means;       // Set Current K_Means
                    CurrentNumberOfClusters = m_Kernel_K_Means.ClusterArrayActualLength;
                    EvaluateClusteringQuality(UpdatedKernel_K_Means, CurrentNumberOfClusters);
                    Dichotom_Clustered_Flag = true;
                    this.NetworkInformation_groupBox.Visible = true;
                    Dichotom_Best9 = SortBestClusters(UpdatedKernel_K_Means, CurrentNumberOfClusters, ref Dichotm_Rest_Of9);
                    Draw_Clusterd_Kernel(m_gImage3, m_Kernel_K_Means, CurrentNumberOfClusters, false);
                    saveBmp(3, m_bmpGraph3, m_bmpHistorySmall, 259, 218);
                    kernelFlag = 0;     // if cluster succeeded ! no need to create another one for sure.
                    InjectChartGraph_ResetGui(UpdatedKernel_K_Means, CurrentNumberOfClusters);
                    this.Clear_data.Enabled = true;    // enable "Clear" button
                    this.ReClusterButton.Enabled = false;
                    this.UndoButton.Enabled = false;
                }
            }
        }// end run_K_MEANS


        void EvaluateClusteringQuality(Kernel_K_Means LocalK_means, int LocNumOfClusters)
        {
            Network CurrentClusterNetwork; Cluster CurrentCluster;
            int numofNodesInCluster = -1;
            float WholeGraphEdgesNum;
            for (int k = 0; k < LocNumOfClusters; k++)
            {
                CurrentCluster = LocalK_means.ClusterArray[k];
                // get the Inner Cluster network 
                if (CurrentCluster.numOfNodes > 1)
                {
                    CurrentCluster.ThisNetwork = PullClusterFromNetworkToTXT(k, ref numofNodesInCluster, LocalK_means);
                    CurrentClusterNetwork = CurrentCluster.ThisNetwork;
                    CurrentCluster.NetworkExists = true;
                    CurrentCluster.numofEdgesIn = CalcSumOfEdges(CurrentClusterNetwork);
                    WholeGraphEdgesNum = ((numofNodesInCluster * (numofNodesInCluster - 1)) / 2);
                    CurrentCluster.edgesPercent = (CurrentCluster.numofEdgesIn / WholeGraphEdgesNum) * 100;
                    while (CurrentCluster.edgesPercent > 100)
                    {
                        CurrentCluster.numofEdgesIn = CurrentCluster.numofEdgesIn * 2 - numofNodesInCluster;
                        CurrentCluster.numofEdgesIn = CurrentCluster.numofEdgesIn / 2;
                        CurrentCluster.edgesPercent = (CurrentCluster.numofEdgesIn / WholeGraphEdgesNum) * 100;
                    }
                    LocalK_means.ClusterArray[k] = CurrentCluster;  // update changes
                }
            }
        }

        ArrayList SortBestClusters(Kernel_K_Means Local_K_Means, int NumOfClusters, ref ArrayList RestOf9)
        {
            RestOf9.Clear();
            var dictionary = new Dictionary<double, int>(); //Dict[edgesPercent,ClusterNumber]
            for (int i = 0; i < NumOfClusters; i++)
            {
                Local_K_Means.ClusterArray[i].edgesPercent += ((i + 1) * 0.000001); // To distinct similar results
                dictionary.Add(Local_K_Means.ClusterArray[i].edgesPercent, i);
            }
            var list = dictionary.Keys.ToList(); // get keys and sort them.
            list.Sort();
            list.Reverse();
            double PercentTotalInList = list.Sum();
            int numOfZeroPercentClusters = 0;
            foreach (double key in list)
                if (Local_K_Means.ClusterArray[dictionary[key]].edgesPercent < 1)
                    numOfZeroPercentClusters++;
            // Loop through keys.
            int ClusterCount = 0, NumOfClusterInBest = 0;
            ArrayList TempBest9 = new ArrayList();
            foreach (double key in list)
            {
                int ClustetrNumOfNodes = Local_K_Means.ClusterArray[dictionary[key]].numOfNodes;
                int NumofClustersToInsertDiffFromZero = list.Count - ClusterCount - numOfZeroPercentClusters;
                double clusterPercent = Local_K_Means.ClusterArray[dictionary[key]].edgesPercent;
                //if <10 all best9 || best9 not full && ( Cluster isnt too small ||  too small & there are no other options to insert
                if (list.Count < 10 || ((NumOfClusterInBest < 9)) && ((clusterPercent > 1 && ClustetrNumOfNodes > 9) || (PercentTotalInList <= clusterPercent) || NumofClustersToInsertDiffFromZero < 9 - NumOfClusterInBest))
                {
                    TempBest9.Add(dictionary[key]);
                    NumOfClusterInBest++;
                }
                else RestOf9.Add(dictionary[key]);
                ClusterCount++;
                PercentTotalInList -= clusterPercent;
            }
            return TempBest9;
        }

        Boolean IsClusterable(int ClusterNumber, ref string ErrorKind, Kernel_K_Means LocKmeans)
        {
            Cluster tmp = LocKmeans.ClusterArray[ClusterNumber];

            if (tmp.numOfNodes < MinNodesPerCluster)
            {
                ErrorKind += "Cluster#" + (ClusterNumber + 1) + " - smaller then " + MinNodesPerCluster + " nodes (" + tmp.numOfNodes + ").\n";
                return false;
            }
            if (tmp.numofEdgesIn < MinEdgesPerCluster)
            {
                ErrorKind += "Cluster#" + (ClusterNumber + 1) + " - has less then  " + MinEdgesPerCluster + " Edges (" + tmp.numofEdgesIn + ").\n";
                return false;
            }

            if (AutomaticDichotom && tmp.edgesPercent > MinEdgesPercentPerCluster)
            {
                return false;
            }
            return true;
        }

        void CMDAnalyzer()
        {
            ProcessStartInfo StartInfotmp = new ProcessStartInfo("cmd.exe");
            StartInfotmp.RedirectStandardInput = true;
            StartInfotmp.RedirectStandardOutput = true;
            StartInfotmp.UseShellExecute = false;
            StartInfotmp.CreateNoWindow = true;
            StartInfotmp.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
            Process CmdConsole = Process.Start(StartInfotmp);
            var standardInput = CmdConsole.StandardInput;
            standardInput.AutoFlush = true;
            var standardOutput = CmdConsole.StandardOutput;
            standardInput.WriteLine("cd " + Directory.GetCurrentDirectory()+"\\Networks");
            //standardInput.WriteLine("del " + netChosen + "-graclus.txt.part." + Convert.ToString(ClusterNum));
            standardInput.WriteLine("java -jar ra.jar");            
            standardInput.WriteLine("exit");
            CmdConsole.WaitForExit();

            standardInput.Close(); // <-- output doesn't arrive before after this line
            string outputData = standardOutput.ReadToEnd();
            
            //Process[] procs = Process.GetProcessesByName("cmd");
            //foreach (Process p in procs) { p.Kill(); }

            standardInput.Close(); // <-- output doesn't arrive before after this line
            standardInput.Dispose(); 
            if (!CmdConsole.HasExited) 
                CmdConsole.Kill();
            CmdConsole.Close(); CmdConsole.Dispose();
            
        }


        Boolean CMDRunProc(string GraclusCommandLines, string netChosen, int ClusterNum)
        {
            ProcessStartInfo StartInfotmp = new ProcessStartInfo("cmd.exe");
            StartInfotmp.RedirectStandardInput = true;
            StartInfotmp.RedirectStandardOutput = true;
            StartInfotmp.RedirectStandardError = true;
            StartInfotmp.UseShellExecute = false;
            StartInfotmp.CreateNoWindow = true;
            StartInfotmp.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            Process CmdConsole=Process.Start(StartInfotmp);
            var standardInput = CmdConsole.StandardInput;
            standardInput.AutoFlush = true;
            var standardOutput = CmdConsole.StandardOutput;
            standardInput.WriteLine("d:");
            standardInput.WriteLine("cd " + graclusFolder);
            standardInput.WriteLine("del " + netChosen + "-graclus.txt.part." + Convert.ToString(ClusterNum));
            standardInput.WriteLine(GraclusCommandLines);
            this.graclus_progressBar.Value = this.graclus_progressBar.Minimum;
            int SleepTimes = 1;
            for (int k = graclus_progressBar.Minimum; k <= graclus_progressBar.Maximum; k++)
            {
                if (((double)k) / graclus_progressBar.Maximum >= (0.1 * ((double)SleepTimes)))
                {
                    SleepTimes++;
                    System.Threading.Thread.Sleep(120);
                    this.graclus_progressBar.PerformStep();
                }
            }
            if (this.graclus_progressBar.Value == graclus_progressBar.Maximum)
                this.Online_Clustering_groupBox.Visible = true;
            standardInput.WriteLine("exit");
            CmdConsole.WaitForExit(2000);
            Process[] procs = Process.GetProcessesByName("graclus");
            foreach (Process p in procs) { p.Kill(); }

            standardInput.Close(); // <-- output doesn't arrive before after this line
            string outputData = standardOutput.ReadToEnd();
            standardInput.Dispose(); standardOutput.Dispose();
            if (!CmdConsole.HasExited) CmdConsole.Kill();
            CmdConsole.Close(); CmdConsole.Dispose();
            if ( outputData.Contains("Timing Information:") && outputData.Contains("Clustering:") && outputData.Contains("Clustering"))
                return true;
            return false;            
        }

        Kernel_K_Means SetGraclusResults(int NumOfClusters, int MultiLevelChosenMatrix)
        {
            Kernel_K_Means Temp_K_Means = new Kernel_K_Means(MultiLevelChosenMatrix, GraclusNumOfClusters, m_Current_Network, -99, 0);
            int UserIndex = 0, ClusterNumberFromTXT = -1;
            string line;
            try
            {
                using (StreamReader sr = new StreamReader("graclus\\" + m_currentNetworkIndex + "-graclus.txt.part." + NumOfClusters))
                {
                    while ((line = sr.ReadLine()) != null)//|| UserIndex <= Temp_K_Means.ClusterNode.Length)
                    {
                        ClusterNumberFromTXT = Convert.ToInt32(line);
                        Temp_K_Means.ClusterNode[UserIndex] = ClusterNumberFromTXT;   // Update ClusterNode
                        Temp_K_Means.ClusterArray[ClusterNumberFromTXT].insertNode(UserIndex);
                        UserIndex++;
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("The file could not be read:");
                Console.WriteLine(e.Message);
            }
            return Temp_K_Means;
        }

                // Initialize main Kernel_K_Means instance and run it 
        private Kernel_K_Means CreateRunK_Means(Network Current_Network)
        {
            Kernel_K_Means temp;
            this.Online_Clustering_panel.Visible = true;           
            for (int i = K_Means_progressBar.Minimum; i <= K_Means_progressBar.Maximum; i++)
                this.K_Means_progressBar.PerformStep();
            if (this.K_Means_progressBar.Value == K_Means_progressBar.Maximum)
                this.Online_Clustering_groupBox.Visible = true;


            temp = new Kernel_K_Means(ChooseMatrix, ChoosenNumOfClusters, Current_Network, sigma, 0);
            if (temp.ErrorFlag == 1) // check matrix errors :
            {
                Error_Msg error = new Error_Msg();
                error.Visible = true;
                error.label1.Text = "The matrix is not sigular.";
                error.label2.Text = "Please choose different parameters.";
                error.label3.Visible = false;
                error.label2.Visible = true;
                return null;
            }            
            else
            {
                if (temp.ClusterArrayActualLength != (ChoosenNumOfClusters))
                { /* if number of clusters after running kernel is different MSG will popup to the user */
                    general_error.Visible = true;
                    general_error.label4.Text = Convert.ToString(numOfClustersAfterKernel);
                    general_error.label5.Text = Convert.ToString(ChoosenNumOfClusters);
                }
                return temp;
            }                
        }


        Cluster[] BackupClusterAndClusterNode(ref int[] newClusterNode, Kernel_K_Means K_meansToBackup)
        {
            Cluster[] TempClusters = new Cluster[CurrentNumberOfClusters];
            Cluster TempCluster;
            newClusterNode = new int[K_meansToBackup.ClusterNode.Length];
            for (int j = 0; j < CurrentNumberOfClusters; j++)
            {
                TempCluster = new Cluster(K_meansToBackup.ClusterArray[j].nodesInCluster.Length,j+1);                
                for (int i = 0; i < K_meansToBackup.ClusterArray[j].numOfNodes; i++)
                {                    
                    TempCluster.insertNode(K_meansToBackup.ClusterArray[j].nodesInCluster[i]);                    
                }
                TempCluster.numOfNodes = K_meansToBackup.ClusterArray[j].numOfNodes;
                TempCluster.numofEdgesIn = K_meansToBackup.ClusterArray[j].numofEdgesIn;
                TempCluster.numofEdgesOut = K_meansToBackup.ClusterArray[j].numofEdgesOut;
                TempCluster.edgesPercent = K_meansToBackup.ClusterArray[j].edgesPercent;
                TempClusters[j] = TempCluster;
            }
            for (int i = 0; i < OriginalNetworkNumOfNodes; i++)
            {
                newClusterNode[i] = K_meansToBackup.ClusterNode[i];
            }
            PreviousNumOfClusters = CurrentNumberOfClusters;
            UndoButton.Enabled = true;  //enable restore backup button ("undo changes")
            return TempClusters;
        }

        // Undo changes in UpdatedKernel_K_Means (ClusterArray And ClusterNode)
        private void UndoButton_Click(object sender, EventArgs e)
        {
            for (int j = 0; j < (PreviousNumOfClusters); j++)
            {                
                UpdatedKernel_K_Means.ClusterArray[j]=PreviousClusters[j];
                UpdatedKernel_K_Means.ClusterArray[j].numOfNodes = PreviousClusters[j].numOfNodes;                    
            }            
            for (int i = 0; i < OriginalNetworkNumOfNodes; i++)
            {
                UpdatedKernel_K_Means.ClusterNode[i] = LastClusterNode[i]; 
            }
            CurrentNumberOfClusters = PreviousNumOfClusters; // Update New Number of Total Clusters   
            UpdatedKernel_K_Means.ClusterArrayActualLength = PreviousNumOfClusters;
            m_gImage3.Clear(Color.Transparent);
            EvaluateClusteringQuality(UpdatedKernel_K_Means, CurrentNumberOfClusters);
            Dichotom_Best9 = SortBestClusters(UpdatedKernel_K_Means, CurrentNumberOfClusters, ref Dichotm_Rest_Of9);
            Dichotom_Clustered_Flag = true;
            saveBmp(3, m_bmpGraph3, m_bmpHistorySmall, 259, 218);
            Draw_Clusterd_Kernel(m_gImage3, UpdatedKernel_K_Means, CurrentNumberOfClusters, false);
            InjectChartGraph_ResetGui(UpdatedKernel_K_Means, CurrentNumberOfClusters);
            Online_Clustering_groupBox.Refresh();
            UndoButton.Enabled = false;
            GlowTimer.Enabled = true;
        }

        /*Injects new Cluster "NewClusterIndex" From DichotomKernel_K_Means
         * into UpdatedKernel_K_Means at "NewLocation"
         * takes nodes info. from "ReplacedClusterIndex" from PreviousKernel_K_Means
         */
        void InjectNewClusterToResults(int NewClusterIndex, int NewLocation, int ReplacedClusterIndex, int NumOfNodesinNet)
        {
            Cluster TempCluster = new Cluster(NumOfNodesinNet, NewLocation+1); // max num of nodes
            int OriginalNodeIndex, GraphNodeIndex;

            //copy nodes content :
            //ClusterNode[i])// clusterNode[i]=the cluster of node i
            for (int i = 0; i < DichotomKernel_K_Means.ClusterArray[NewClusterIndex].numOfNodes; i++)
            {   // insert all nodes from cluster
                GraphNodeIndex = DichotomKernel_K_Means.ClusterArray[NewClusterIndex].nodesInCluster[i]; // get Graph index from results
                // get original Index from Initial Graph (from previous)
                OriginalNodeIndex = PreviousKernel_K_Means.ClusterArray[ReplacedClusterIndex].nodesInCluster[GraphNodeIndex];
                // insert the oroginal index into the new cluster 
                TempCluster.insertNode(OriginalNodeIndex);
                UpdatedKernel_K_Means.ClusterNode[OriginalNodeIndex] = NewLocation;     // ClusterNode[i] = The cluster of node i                    
            }
            UpdatedKernel_K_Means.ClusterArray[NewLocation] = TempCluster;
        }

        private void InjectChartGraph_ResetGui(Kernel_K_Means Local2_K_Means, int Local2NumOfClusters)
        {
            FillTable(ref dataGridView1, Local2_K_Means, Local2NumOfClusters,false);
            SelectAllbox.Checked = false;            
            if (SelectBox2!=null)
                for (int i = 0; i < SelectBox2.Length; i++)
                {
                    SelectBox2[i].Enabled = false;
                    SelectBox2[i].Visible = false;
                    NetworkInformation_groupBox.Controls.Remove(SelectBox2[i]);                
                }

            // add CheckBoxes for each cluster :
            SelectBox2 = new System.Windows.Forms.CheckBox[CurrentNumberOfClusters];
            for (int i = 0; i < CurrentNumberOfClusters; i++)
            {
                SelectBox2[i] = new System.Windows.Forms.CheckBox();                
                SelectBox2[i].Appearance = System.Windows.Forms.Appearance.Button;
                SelectBox2[i].AutoEllipsis = true;
                SelectBox2[i].BackColor = System.Drawing.Color.SkyBlue;  
                SelectBox2[i].Font = new System.Drawing.Font("Narkisim", 7.8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
                SelectBox2[i].CheckAlign = System.Drawing.ContentAlignment.MiddleCenter;
                SelectBox2[i].Location = new System.Drawing.Point((i / 10)*45 + 545, 206 + ((i%10)*30));
                SelectBox2[i].Name = "SelectBox" + Convert.ToString(i);
                SelectBox2[i].Size = new System.Drawing.Size(33, 25);
                SelectBox2[i].TabIndex = 34;
                SelectBox2[i].UseVisualStyleBackColor = false;
                SelectBox2[i].Text = Convert.ToString(i + 1);                
                NetworkInformation_groupBox.Controls.Add(SelectBox2[i]);
            }
            FillGraph(ref this.chart2);      // results tab 

            this.Dichotom_button.Enabled = false;
            this.Run_K_Means_button.Enabled = false;
            this.KernelMatrix_comboBox.Enabled = false;
            //this.NumOfClusterKernel_comboBox.Enabled = false;
            this.Sigma_textBox.Enabled = false;
        }

        private void GlowTimer_Tick(object sender, EventArgs e)
        {
            // disable timer and set the color back to white            
            Color currentColor;
            if (timerindex % 2==0)    // first and another
                currentColor = Color.LawnGreen;           
            else
                currentColor = Color.White;
            if (dataGridView1.Rows.Count >ReplacedClusterIndex)
                dataGridView1.Rows[ReplacedClusterIndex].DefaultCellStyle.BackColor = currentColor;
            if (dataGridView1.Rows.Count > CurrentNumberOfClusters-1)
                dataGridView1.Rows[CurrentNumberOfClusters-1].DefaultCellStyle.BackColor = currentColor; 
            timerindex++;
            if (timerindex==6)
            {
                GlowTimer.Enabled = false;
                timerindex = 0;
            }
            dataGridView1.Refresh();
        }


// Pull Cluster original nodes from old matrix to new one and export to txt
        Network PullClusterFromNetworkToTXT(int ClusterIndex, ref int numofnodesIntxt1, Kernel_K_Means LocKmeans)
        {
            int tempnumofnodes = 0;
            Network TempDichotomNetwork;
            if (!LocKmeans.ClusterArray[ClusterIndex].NetworkExists || LocKmeans.ClusterArray[ClusterIndex].numofEdgesIn < 5)
            {           
                int NodesCinCluster = LocKmeans.ClusterArray[ClusterIndex].numOfNodes;
                    int originalI = 0, originalJ = 0;
                    double[,] NewCMatrix = new double[NodesCinCluster, NodesCinCluster]; // new matrix
                    TextWriter tw = new StreamWriter("NewClusterMatrix.txt", false);  // Overwrite if exists
                    for (int i = 0; i < NodesCinCluster; i++)
                    {
                        originalI = LocKmeans.ClusterArray[ClusterIndex].nodesInCluster[i]; // get original index of node i in old matrix
                        if (i != 0)
                            tw.Write("\n");
                        for (int j = 0; j < NodesCinCluster; j++)
                        {
                            originalJ = LocKmeans.ClusterArray[ClusterIndex].nodesInCluster[j]; // old matrix - node j index
                            NewCMatrix[i, j] = LocKmeans.net.adjacnyMatrix.Data[originalI, originalJ];
                            tw.Write(Convert.ToString(NewCMatrix[i, j]));
                        }
                    }
                    tw.Close();
                    TempDichotomNetwork= new Network("NewClusterMatrix.txt");                                
            }
            else // if network exists for cluster, return it.
                TempDichotomNetwork = LocKmeans.ClusterArray[ClusterIndex].ThisNetwork; 
            // update numofNodes
            TempDichotomNetwork.get_numOfNodes(ref tempnumofnodes);
            numofnodesIntxt1=tempnumofnodes;
            TempDichotomNetwork.Calc_adjacnyKernel(tempnumofnodes, tempnumofnodes);   // Calc Matrix
            return (TempDichotomNetwork);
        }

        int CalcSumOfEdges(Network NetworkE)
        {
            double SumOfEdges = 0;
            for (int i = 0; i < NetworkE.numOfNodes; i++)
            {
                for (int j = 0; j < NetworkE.numOfNodes; j++)
                {
                    SumOfEdges += NetworkE.adjacnyMatrix[i, j];
                }
            }
            SumOfEdges = SumOfEdges - NetworkE.numOfNodes;            
            if (SumOfEdges < 0)
                SumOfEdges = 0;
            SumOfEdges = SumOfEdges / 2;           
            return (int)SumOfEdges;
        }

        private void AutoDichotomCheck_CheckedChanged(object sender, EventArgs e)
        {
            AutomaticDichotom = AutoDichotomCheck.Checked;
            this.StopingRules.Enabled = AutomaticDichotom;
            this.MinNodes.Enabled = AutomaticDichotom;
            this.MinNodesTextbox.Enabled = AutomaticDichotom;
            this.minEdges.Enabled = AutomaticDichotom;
            this.MinEdgesTextbox.Enabled = AutomaticDichotom;
 
            // Show other parameters
        }

        private void SelectAllbox_CheckedChanged(object sender, EventArgs e)
        {
            if (manualDisableSelectAll)
            {
                manualDisableSelectAll = false;
                return;
            }
            Boolean Newstate=false;
            if (SelectAllbox.Checked)
                Newstate = true;
           
            for (int i = 0; (i < CurrentNumberOfClusters && i< SelectBox2.Length); i++)
            {
                SelectBox2[i].Checked = Newstate;
            }
        }


        public void writeInfo()
                {
                    int net = m_currentNetworkIndex;
                  using (StreamWriter wr = new StreamWriter("Network"+net+"_matrix"+ChooseMatrix+"_info.txt", false))
                  {
                      for (int i = 0; i < 4; i++)
                          wr.WriteLine(history[i]);

                      wr.WriteLine(m_Current_Network.numOfNodes);
                  }
                }

// Draws Network in 1st tab - called from ConvertNetwork_Button_Click(
            public void Draw_Network()
            {             
                Matrix adjMat;
                int matrix_size = 0;
                this.m_Current_Network.get_numOfNodes(ref matrix_size);
                adjMat = new Matrix(matrix_size);
                this.m_Current_Network.get_adjacnyMatrix(ref adjMat.Data);
                Random rand = new Random();                
                nodes1 = new Point[adjMat.Data.GetLength(1)]; // coardinates of each node
                PointF temp1=new PointF();
                PointF temp2 = new PointF();
                this.m_gImage1.Clear(Color.Transparent);

                for (int i = 0; i < adjMat.Data.GetLength(1); i++)
                {                
                    nodes1[i].X = rand.Next(1150)+5;
                    nodes1[i].Y = rand.Next(635)+5;
                }
                Pen blackPen = new Pen(Color.FromArgb(255, 0, 0, 0), 2);
        
               for (int i = 0; i < adjMat.Data.GetLength(1); i++)
                 for (int j = 0; j < adjMat.Data.GetLength(1); j++)
                    if ((adjMat[i, j] == 1) && (i < j))
                    {
                        temp1 = calcPosition(nodes1[i], 25);
                        temp2 = calcPosition(nodes1[j],25);
                        m_gImage1.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //   g.SmoothingMode = HighQuality;
                        Pen temp = new Pen(Color.SteelBlue);
                        m_gImage1.DrawLine(Pens.SteelBlue, temp1.X, temp1.Y, temp2.X, temp2.Y);
                    }

                for (int i = 0; i < adjMat.Data.GetLength(1); i++)
                {
                    Icon icon1 = new Icon("icons\\blue.ico");
                    Rectangle recta = new Rectangle(nodes1[i].X - 10, nodes1[i].Y - 7, 34, 38);                    
                    m_gImage1.DrawIcon(icon1, recta);
                }
        }//Draw_Network

        Boolean NeedToDrawLine(int Nodei, int Nodej, Kernel_K_Means KMeans, int NumOfClusters, Boolean FromGraclusFlag)
        {
            ArrayList G_B9 = Graclus_Best9, B_9 = Dichotom_Best9;
            int Clusteri = KMeans.ClusterNode[Nodei], Clusterj = KMeans.ClusterNode[Nodej];
                if (FromGraclusFlag && G_B9.Contains(Clusteri) && G_B9.Contains(Clusterj) ) 
                    return true;
                else if (!FromGraclusFlag && Dichotom_Best9.Contains(Clusteri) && Dichotom_Best9.Contains(Clusterj) )
                    return true;
            return false;
        }


        Boolean NeedToDrawNode(int NodeIndex, Kernel_K_Means KMeans, int NumOfClusters, Boolean FromGraclusFlag)
        {
            ArrayList G_B9 = Graclus_Best9, B_9 = Dichotom_Best9;
            int ClusterOfNode = KMeans.ClusterNode[NodeIndex];
                if (FromGraclusFlag && G_B9.Contains(ClusterOfNode))
                    return true;
                else if (!FromGraclusFlag && Dichotom_Best9.Contains(ClusterOfNode))
                    return true;
            return false;
        }

         void Draw_Clusterd_Kernel(Graphics current_image, Kernel_K_Means Current_KMeans,int NumOfClusters, Boolean FromGraclusFlag)
        {
            Matrix adjMat; int[] ClusterSorted = new int[NumOfClusters], ClustersNewLoc = new int[NumOfClusters];
            int matrix_size = 0; 
            this.m_Current_Network.get_numOfNodes(ref matrix_size);
            adjMat = new Matrix(matrix_size);
            this.m_Current_Network.get_adjacnyMatrix(ref adjMat.Data);
            Point temp1 = new Point(), temp2 = new Point();
            ArrayList LocalBest9 = Dichotom_Best9, LocalRestOf9 = Dichotm_Rest_Of9;            
            if (FromGraclusFlag)     // Set Correct ArrayLists if From Graclus
            {
                LocalBest9 = Graclus_Best9;
                LocalRestOf9 = Graclus_Rest_Of9;
            }
            int k = 0;            // Get BestOf9 And the rest
            foreach (int ClusterNumber in LocalBest9)
            {
                ClustersNewLoc[ClusterNumber] = k;
                ClusterSorted[k++] = ClusterNumber;
            }
            foreach (int ClusterNumber in LocalRestOf9)
            {
                ClustersNewLoc[ClusterNumber] = k;
                ClusterSorted[k++] = ClusterNumber;
            }
            Current_KMeans.calcPositionOfNodes(ClusterSorted);    // this size if drawing in 2nd tab add if other tabs other sizes
            Pen Color;
            for (int i = 0; i < Current_KMeans.numOfNodesKernel; i++)
                for (int j = 0; j < Current_KMeans.numOfNodesKernel; j++)
                    if ((i < j) && (adjMat[i, j] == 1) && NeedToDrawLine(i, j, Current_KMeans, NumOfClusters, FromGraclusFlag))
                    {                        
                        if (Current_KMeans.ClusterNode[i] == Current_KMeans.ClusterNode[j])
                            Color = Pens.DarkOliveGreen;
                        else Color = Pens.LightBlue;
                        temp1 = calcPosition(Current_KMeans.kernalCoard[i], 34);
                        temp2 = calcPosition(Current_KMeans.kernalCoard[j], 34);
                        current_image.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //   g.SmoothingMode = HighQuality;
                        current_image.DrawLine(Color, temp1.X, temp1.Y, temp2.X, temp2.Y);                        
                    }

            int ClusterOfNode = 0;
            for (int i = 0; i < Current_KMeans.numOfNodesKernel; i++)// draw all nodes in kernel
            {                
                if (NeedToDrawNode(i, Current_KMeans, NumOfClusters, FromGraclusFlag) )
                {
                    ClusterOfNode=Current_KMeans.ClusterNode[i];                    
                    ClusterOfNode = ClustersNewLoc[ClusterOfNode];                    
                    Rectangle recta = new Rectangle(Current_KMeans.kernalCoard[i].X, Current_KMeans.kernalCoard[i].Y, 34, 38);
                    switch (ClusterOfNode)// clusterNode[i]=the cluster of node i
                    {
                        case 0:
                            current_image.DrawIcon(icon_Array[0], recta);
                            break;
                        case 1:
                            current_image.DrawIcon(icon_Array[1], recta);
                            break;
                        case 2:
                            current_image.DrawIcon(icon_Array[2], recta);
                            break;
                        case 3:
                            current_image.DrawIcon(icon_Array[3], recta);
                            break;
                        case 4:
                            current_image.DrawIcon(icon_Array[4], recta);
                            break;
                        case 5:
                            current_image.DrawIcon(icon_Array[5], recta);
                            break;
                        case 6:
                            current_image.DrawIcon(icon_Array[6], recta);
                            break;
                        case 7:
                            current_image.DrawIcon(icon_Array[7], recta);
                            break;
                        case 8:
                            current_image.DrawIcon(icon_Array[8], recta);
                            break;
                        case 9:
                            current_image.DrawIcon(icon_Array[9], recta);
                            break;
                    }
                    if (Current_KMeans.InterestsExists)
                        Current_KMeans.DrawPecenteges(ClusterSorted, current_image, FromGraclusFlag);
                }
            }
        }
        

        Point calcPosition(Point a, int size)
        {
            a.X = a.X + size / 2;
            a.Y = a.Y + size / 2;
            return a;
        }

        private void Results_tabPage3_Enter(object sender, EventArgs e)
        {  
            if (  Dichotom_Clustered_Flag)
                this.clustered_network.Visible = true;
            if (Graclus_Clustered_Flag)
                this.Original_network.Visible = true;    
            
            this.chart2.Visible = true;
            this.InterstChart.Visible = true;       
        }
        //painter : 1st tab original network
        private void graphPaint(object sender, PaintEventArgs e)
        {
            Point p = new Point(6, 6);
            e.Graphics.DrawImage(m_bmpGraph1, p);
        }

        //painter :  results tab Graclus
        private void resultPaint(object sender, PaintEventArgs e)
        {
            Point p = new Point(1, 1);
            //m_bmpGraph4 = ResizeBitmap(m_bmpGraph1, 648, 347);
            m_bmpGraph4 = ResizeBitmap(m_bmpGraph3_Graclus, 520, 350);
            
            e.Graphics.DrawImage(m_bmpGraph4, p);
        }        
        //painter :  results tab Dichotom Clustered network
        private void ClusteredresultPaint(object sender, PaintEventArgs e)
        {
            Point p = new Point(1, 1);
            m_bmpGraph5 = ResizeBitmap(m_bmpGraph3, 520, 350);
            e.Graphics.DrawImage(m_bmpGraph5, p);
        }
        //painter :  Clustering tab Dichotom Clusterd network
        private void ClusterdkernelPaint(object sender, PaintEventArgs e)
        {
            Point p = new Point(1, 1);
            e.Graphics.DrawImage(m_bmpGraph3, p);
        }
        //painter :  Clustering tab Graclus Clusterd network
        private void Graclus_ClusterdkernelPaint(object sender, PaintEventArgs e)
        {
            Point p = new Point(1, 1);
            e.Graphics.DrawImage(m_bmpGraph3_Graclus, p);
        }

        public Bitmap ResizeBitmap(Bitmap b, int nWidth, int nHeight)
        {
            Bitmap result = new Bitmap(nWidth, nHeight);
            using (Graphics g = Graphics.FromImage((Image)result))
                g.DrawImage(b, 0, 0, nWidth, nHeight);
            return result;
        }

        private void FillInterestGraph(ref Chart chart1)
        {
            chart1.Visible = true;
            chart1.Series.Clear();
            double ClusterInterestpercent;
            System.Windows.Forms.DataVisualization.Charting.Series[] Ser1 = new System.Windows.Forms.DataVisualization.Charting.Series[2];
            for (int i = 0; i < 2; i++)
            {
                Ser1[i] = new System.Windows.Forms.DataVisualization.Charting.Series();
                Ser1[i].BackGradientStyle = System.Windows.Forms.DataVisualization.Charting.GradientStyle.VerticalCenter;
                Ser1[i].BackImageAlignment = System.Windows.Forms.DataVisualization.Charting.ChartImageAlignmentStyle.Center;
                Ser1[i].BackImageTransparentColor = System.Drawing.Color.Transparent;
                Ser1[i].BorderColor = System.Drawing.Color.DarkSlateGray;
                Ser1[i].BorderDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.DashDot;
                Ser1[i].BorderWidth = 0;
                Ser1[i].ChartArea = "ChartArea1";
                Ser1[i].CustomProperties = "DrawingStyle=Wedge, LabelStyle=Top";
                Ser1[i].LabelBackColor = System.Drawing.Color.Transparent;
                Ser1[i].ShadowColor = System.Drawing.Color.Teal;
                Ser1[i].ShadowOffset = 10;
                if (i == 0)
                {
                    Ser1[i].Color = System.Drawing.Color.DodgerBlue;
                    Ser1[i].Name = "Dichotom";
                    Ser1[i].ShadowColor = System.Drawing.Color.Teal;
                }
                else
                {
                    Ser1[i].Name = "Multi-Level";
                    Ser1[i].Color = System.Drawing.Color.Salmon;
                    Ser1[i].ShadowColor = System.Drawing.Color.PeachPuff;
                }
            }
            if (Dichotom_Clustered_Flag)
            {
                chart1.Series.Add(Ser1[0]);
                for (int i = 1; i <= CurrentNumberOfClusters; i++)
                {
                    string interestpercentstr = UpdatedKernel_K_Means.ClusterArray[i - 1].interest1stpercent;
                    if (interestpercentstr.Length != 0 && !interestpercentstr.Contains(" "))
                    {
                        ClusterInterestpercent = Convert.ToDouble(UpdatedKernel_K_Means.ClusterArray[i - 1].interest1stpercent);
                        if (ClusterInterestpercent > 0.9 && UpdatedKernel_K_Means.ClusterArray[i - 1].numOfNodes > 5)
                            chart1.Series["Dichotom"].Points.AddXY(Convert.ToString(i), ClusterInterestpercent);//the string is the name of the slice'the value is the number.
                    }
                }
                chart1.Series["Dichotom"].IsValueShownAsLabel = true;
            }
            if (Graclus_Clustered_Flag)
            {
                chart1.Series.Add(Ser1[1]);
                for (int i = 1; i <= GraclusNumOfClusters; i++)
                {
                    string interestpercentstr = Graclus_K_Means.ClusterArray[i - 1].interest1stpercent;
                    if (interestpercentstr.Length != 0 && !interestpercentstr.Contains(" "))
                    {
                        ClusterInterestpercent = Convert.ToDouble(Graclus_K_Means.ClusterArray[i - 1].interest1stpercent);
                        if (ClusterInterestpercent > 0.9 && Graclus_K_Means.ClusterArray[i - 1].numOfNodes > 5)
                            chart1.Series["Multi-Level"].Points.AddXY(Convert.ToString(i), ClusterInterestpercent);//the string is the name of the slice'the value is the number.
                    }
                }
                chart1.Series["Multi-Level"].IsValueShownAsLabel = true;
            }
        }


        private void FillGraph(ref Chart chart1)
        {
            chart1.Visible = true;
            chart1.Series.Clear();
            System.Windows.Forms.DataVisualization.Charting.Series[] Ser1 = new System.Windows.Forms.DataVisualization.Charting.Series[2];
            for (int i = 0; i < 2; i++)
            {
                Ser1[i] = new System.Windows.Forms.DataVisualization.Charting.Series();
                Ser1[i].BackGradientStyle = System.Windows.Forms.DataVisualization.Charting.GradientStyle.VerticalCenter;
                Ser1[i].BackImageAlignment = System.Windows.Forms.DataVisualization.Charting.ChartImageAlignmentStyle.Center;
                Ser1[i].BackImageTransparentColor = System.Drawing.Color.Transparent;
                Ser1[i].BorderColor = System.Drawing.Color.DarkSlateGray;
                Ser1[i].BorderDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.DashDot;
                Ser1[i].BorderWidth = 0;
                Ser1[i].ChartArea = "ChartArea1";
                Ser1[i].CustomProperties = "DrawingStyle=Wedge, LabelStyle=Top";
                Ser1[i].LabelBackColor = System.Drawing.Color.Transparent;
                Ser1[i].ShadowColor = System.Drawing.Color.Teal;
                Ser1[i].ShadowOffset = 10;
                if (i == 0)
                {
                    Ser1[i].Color = System.Drawing.Color.DodgerBlue;
                    Ser1[i].Name = "Dichotom";
                    Ser1[i].ShadowColor = System.Drawing.Color.Teal;
                }
                else
                {
                    Ser1[i].Name = "Multi-Level";
                    Ser1[i].Color = System.Drawing.Color.Salmon;
                    Ser1[i].ShadowColor = System.Drawing.Color.PeachPuff;
                }                
            }
            if (Dichotom_Clustered_Flag)
            {
                chart1.Series.Add(Ser1[0]);
                for (int i = 1; i <= CurrentNumberOfClusters; i++)
                {
                    if (UpdatedKernel_K_Means.ClusterArray[i - 1].edgesPercent > 0.9 && UpdatedKernel_K_Means.ClusterArray[i - 1].numOfNodes > 5)
                        chart1.Series["Dichotom"].Points.AddXY(Convert.ToString(i), Convert.ToInt32(UpdatedKernel_K_Means.ClusterArray[i - 1].edgesPercent));//the string is the name of the slice'the value is the number.
                }
                chart1.Series["Dichotom"].IsValueShownAsLabel = true;
            }
            if (Graclus_Clustered_Flag)
            {
                chart1.Series.Add(Ser1[1]);
                for (int i = 1; i <= GraclusNumOfClusters; i++)
                {
                    if (Graclus_K_Means.ClusterArray[i - 1].edgesPercent > 0.9 && Graclus_K_Means.ClusterArray[i - 1].numOfNodes > 5)
                        chart1.Series["Multi-Level"].Points.AddXY(Convert.ToString(i), Convert.ToInt32(Graclus_K_Means.ClusterArray[i - 1].edgesPercent));//the string is the name of the slice'the value is the number.
                }
                chart1.Series["Multi-Level"].IsValueShownAsLabel = true;
            }
            FillTotalsGraph(ref TotalsGraphChart);
        }


        void FillTotalsGraph(ref Chart TotalsGraph)
        {
            TotalsGraph.Visible = true;
            TotalsGraph.Series.Clear();
            System.Windows.Forms.DataVisualization.Charting.Series[] Ser1 = new System.Windows.Forms.DataVisualization.Charting.Series[3];
            for (int i = 0; i < 3; i++)
            {
                Ser1[i] = new System.Windows.Forms.DataVisualization.Charting.Series();
                Ser1[i].BackGradientStyle = System.Windows.Forms.DataVisualization.Charting.GradientStyle.VerticalCenter;
                Ser1[i].BackImageAlignment = System.Windows.Forms.DataVisualization.Charting.ChartImageAlignmentStyle.Center;
                Ser1[i].BackImageTransparentColor = System.Drawing.Color.Transparent;
                Ser1[i].BorderColor = System.Drawing.Color.DarkSlateGray;
                Ser1[i].BorderDashStyle = System.Windows.Forms.DataVisualization.Charting.ChartDashStyle.DashDot;
                Ser1[i].BorderWidth = 0;
                Ser1[i].ChartArea = "ChartArea1";
                Ser1[i].CustomProperties = "DrawingStyle=Wedge, LabelStyle=Top";
                Ser1[i].LabelBackColor = System.Drawing.Color.Transparent;
                Ser1[i].ShadowColor = System.Drawing.Color.Teal;
                Ser1[i].ShadowOffset = 10;
                if (i == 1)
                {
                    Ser1[i].Color = System.Drawing.Color.DodgerBlue;
                    Ser1[i].Name = "Dichotom";
                    Ser1[i].ShadowColor = System.Drawing.Color.Teal;
                }
                else if (i == 2)
                {
                    Ser1[i].Name = "Multi-Level";
                    Ser1[i].Color = System.Drawing.Color.Salmon;
                    Ser1[i].ShadowColor = System.Drawing.Color.PeachPuff;
                }
                else
                {
                    Ser1[i].Name = "Original";
                    Ser1[i].Color = System.Drawing.Color.Gray;
                    Ser1[i].ShadowColor = System.Drawing.Color.LightGray;
                }
            }
            TotalsGraph.Series.Add(Ser1[0]);
            TotalsGraph.Series["Original"].Points.AddXY("1", Convert.ToDouble(Orignalpercent));//the string is the name of the slice'the value is the number.
            TotalsGraph.Series["Original"].IsValueShownAsLabel = true;

            if (Dichotom_Clustered_Flag)
            {
                TotalsGraph.Series.Add(Ser1[1]);
                TotalsGraph.Series["Dichotom"].Points.AddXY("1", Convert.ToDouble(this.avgK_klik.Text));//the string is the name of the slice'the value is the number.
                TotalsGraph.Series["Dichotom"].IsValueShownAsLabel = true;
            }
            if (Graclus_Clustered_Flag)
            {
                TotalsGraph.Series.Add(Ser1[2]);
                TotalsGraph.Series["Multi-Level"].Points.AddXY("1", Convert.ToDouble(this.Graclus_avgK_klik.Text));//the string is the name of the slice'the value is the number.
                TotalsGraph.Series["Multi-Level"].IsValueShownAsLabel = true;
            }

        }
        

        private void pictureBox2_Click(object sender, EventArgs e)  // Graph button click - 2nd tab 
        {    // Draw And enable :      
            if (GraphGraclus != null)
                this.GraphGraclus.Dispose();
            this.GraphGraclus = new Average_graph();
            FillGraph(ref this.GraphGraclus.chart1); // 2nd tab graph
            this.GraphGraclus.Visible = true;                       
        }


        private void FillTable(ref DataGridView dataGridView_temp , Kernel_K_Means Current_KMeans,int LocalNumberOfClusters, Boolean GraclusResults)
        {
            double sum = 0; int ClustersInAvg = 0;
            int[] ClusterSorted = new int[LocalNumberOfClusters], ClustersNewLoc = new int[LocalNumberOfClusters];
            string temp2 = ""; string[] temp1 = new string[OriginalNetworkNumOfNodes];
            dataGridView_temp.Rows.Clear(); ArrayList LocalBest9 = Dichotom_Best9, LocalRestOf9 = Dichotm_Rest_Of9;            
            if (GraclusResults)     // Set Correct ArrayLists if From Graclus
            {
                LocalBest9 = Graclus_Best9;
                LocalRestOf9 = Graclus_Rest_Of9;
            }
            foreach (DataGridViewColumn c in dataGridView_temp.Columns)
            {
                c.DefaultCellStyle.Font = new Font("Narkisim", 16f, FontStyle.Regular, GraphicsUnit.Pixel);                
            }
            dataGridView_temp.ColumnHeadersDefaultCellStyle.Font = new Font("Narkisim", 16f, FontStyle.Regular, GraphicsUnit.Pixel);
            numOfClustersAfterKernel = 0;
            DataGridViewImageColumn iconColumn = new DataGridViewImageColumn();
            Bitmap TempIconBMP;
            int k = 0;            // Get BestOf9 And the rest
            foreach (int ClusterNumber in LocalBest9)
            {
                ClustersNewLoc[ClusterNumber] = k;
                ClusterSorted[k++] = ClusterNumber;
            }
            foreach (int ClusterNumber in LocalRestOf9)
            {
                ClustersNewLoc[ClusterNumber] = k;
                ClusterSorted[k++] = ClusterNumber;
            }
            int i = 0;
            for (int m = 0; m < LocalNumberOfClusters; m++) // adding to table
            {   // i= cluster ID
                i = ClusterSorted[m]; 
                if (Current_KMeans.ClusterArray[i].edgesPercent>1)
                {
                    sum+=Current_KMeans.ClusterArray[i].edgesPercent;
                    ClustersInAvg++;
                }
                if (Current_KMeans.ClusterArray[i].numOfNodes != 0)     
                {
                    TempIconBMP = icon_Array[m].ToBitmap();
                    iconColumn.Image = ResizeBitmap(TempIconBMP, 25, 28);
                    for (int j = 0; j < Current_KMeans.ClusterArray[i].numOfNodes; j++)
                    {
                        temp1[j] = Convert.ToString(Current_KMeans.ClusterArray[i].nodesInCluster[j]);
                        temp2 += temp1[j] + ",";
                    }
                    string EdgesPercentStr = "0", InterestPerc, MemberOfPerc, InterestTXT, MemberOfTXT;
                    if (Current_KMeans.ClusterArray[i].edgesPercent > 0.22)
                        EdgesPercentStr = Convert.ToString(Current_KMeans.ClusterArray[i].edgesPercent);
                    if (EdgesPercentStr.Length>5)
                        EdgesPercentStr = EdgesPercentStr.Substring(0, 5);
                    /*        public int numOfUsersWithInterests=-1, numOfUsers1stInterests=-1;
                              public int numOfUsersWithMemberOf = -1, numOfUsers1stMemberOf = -1;
                              public string Interests1st = " ", MemberOf1st = " ";   */
                    if (Current_KMeans.InterestsExists)
                    {
                        int tmpTotal = Current_KMeans.ClusterArray[i].numOfUsersWithInterests, Tmp1st = Current_KMeans.ClusterArray[i].numOfUsers1stInterests;
                        double result = (( Convert.ToDouble(Tmp1st) / Convert.ToDouble(tmpTotal) ) * 100);
                        InterestPerc = Convert.ToString(Convert.ToInt32(result));
                        Current_KMeans.ClusterArray[i].interest1stpercent = InterestPerc;
                        tmpTotal = Current_KMeans.ClusterArray[i].numOfUsersWithMemberOf; Tmp1st = Current_KMeans.ClusterArray[i].numOfUsers1stMemberOf;
                        result = ((Convert.ToDouble(Tmp1st) / Convert.ToDouble(tmpTotal)) * 100);
                        if (tmpTotal != 0)
                            MemberOfPerc = Convert.ToString(Convert.ToInt32(result));
                        else MemberOfPerc = "";
                        InterestTXT = Current_KMeans.ClusterArray[i].Interests1st;
                        MemberOfTXT = Current_KMeans.ClusterArray[i].MemberOf1st;
                    }
                    else
                        InterestPerc=MemberOfPerc=InterestTXT=MemberOfTXT= " ";                         

                    dataGridView_temp.Rows.Add(i + 1, iconColumn.Image, Convert.ToString(Current_KMeans.ClusterArray[i].numOfNodes), EdgesPercentStr, InterestTXT, InterestPerc, MemberOfTXT, MemberOfPerc, temp2);
                    temp2 = "";
                    numOfClustersAfterKernel++;
                    SumOfNodes += Current_KMeans.ClusterArray[i].numOfNodes;
                }                    
            }               
            foreach (DataGridViewRow row in dataGridView_temp.Rows)
            {
                row.Height = 30;
            }
            this.Network_number_results.Text = this.Network_number.Text;
            this.NumOfNodes_Results.Text = this.Number_of_nodes_in_network.Text;
            int Improvement;
            if (!GraclusResults)
            {
                this.Network_number.Text = Convert.ToString(m_currentNetworkIndex);  // Network number
                this.Number_of_nodes_in_network.Text = Convert.ToString(OriginalNetworkNumOfNodes);
                this.Number_of_clusters.Text = Convert.ToString(LocalNumberOfClusters);    // num of clusters// CurrentNumberOfClusters
                 this.avgK_klik.Text = Convert.ToString(sum / ClustersInAvg);
                if (avgK_klik.Text.Length > 5)
                    this.avgK_klik.Text = this.avgK_klik.Text.Substring(0, 5);
                //results tab                       -- num of clusters, nodes and network ID
                //Improvement = Convert.ToInt32((100 * (sum / ClustersInAvg) / Convert.ToInt32(Orignalpercent)));
                //this.Density_improv.Text = Convert.ToString(Improvement)+"%";
            }
            else
            {
                this.Graclus_Network_number.Text = Convert.ToString(m_currentNetworkIndex);  // Network number
                this.Graclus_Number_of_nodes_in_network.Text = Convert.ToString(OriginalNetworkNumOfNodes);
                this.Graclus_Number_of_clusters.Text = Convert.ToString(LocalNumberOfClusters);    // num of clusters// CurrentNumberOfClusters
                this.Graclus_avgK_klik.Text= Convert.ToString(sum / ClustersInAvg);


                if (this.Graclus_avgK_klik.Text.Length > 5)
                    this.Graclus_avgK_klik.Text = this.Graclus_avgK_klik.Text.Substring(0, 5);
                //Improvement = Convert.ToInt32(100* ((sum / ClustersInAvg) / Convert.ToInt32(Orignalpercent)) );
                //this.Graclus_Density_improv.Text = Convert.ToString(Improvement)+"%";
            }      
        }        

        // Export All Clusters Results to txt file
        private void ExportResultsToTXT(Kernel_K_Means Current_KMeans, int NumOfClusters, Boolean FromGraclus)
        {            
            int NetworkNumber = m_currentNetworkIndex;
            int numOfNodes =OriginalNetworkNumOfNodes;
            string path = Directory.GetCurrentDirectory() + "\\Networks\\ClusterResults.txt";
            /*if (FromGraclus)
                path+="-Graclus.txt";
            else path+="-Dichotom.txt";*/
            TextWriter tw = new StreamWriter(path, false);  // Overwrite if exists
            string choosenmatix="Ratio-Association";
            if (Current_KMeans.m_kMatrix==2)
                choosenmatix="Normalized-Cut";
            else if (Current_KMeans.m_kMatrix==3)
                choosenmatix = "Ratio-Cut";
            if (FromGraclus)
                choosenmatix += " Graclus";
            else choosenmatix += " Dichotom";
            String Number_of_clusters = Convert.ToString(NumOfClusters);    // num of clusters
            String Network_Number = Convert.ToString(NetworkNumber);        // Network number
            String NumOfNodes = Convert.ToString(numOfNodes);
            String CurrentClusterString;
            String CurrentUser;

            tw.WriteLine(Network_Number+" "+NumOfNodes+" "+Number_of_clusters);
            tw.WriteLine(choosenmatix);
            
            for (int i = 0; i < NumOfClusters; i++) // adding to table
            {   // i= cluster ID
                if (Current_KMeans.ClusterArray[i].numOfNodes != 0) // if cluster isn't empty from nodes
                {       
                    CurrentClusterString=Convert.ToString(i);
                    for (int j = 0; j < Current_KMeans.ClusterArray[i].numOfNodes; j++)
                    {
                        CurrentUser = Convert.ToString(Current_KMeans.ClusterArray[i].nodesInCluster[j]);
                        tw.WriteLine(CurrentClusterString + " " + CurrentUser);
                    }
                    numOfClustersAfterKernel++;
                    SumOfNodes += Current_KMeans.ClusterArray[i].numOfNodes;
                }
            }
                tw.Close();
        }  
        
        private void sigma_textBox_Leave(object sender, EventArgs e)
        { 
            string sigmaStr;
            char[] charArr;
            int i;
            sigmaStr = this.Sigma_textBox.Text;
            charArr = new char[sigmaStr.Length];
            charArr = sigmaStr.ToCharArray();
            sigmaDotEntered_flag=0;
            for (i = 0; i < sigmaStr.Length; i++)
            {
                if (i == 0)//if it's the first digit it cannot be a '.', i=0 is the first digit
                {
                    if ((charArr[i] <= 48 && charArr[i] != 45) || charArr[i] > 57)//'48' asci of 0 ,  '57' asci of 9,   '46' asci of . , '45' is the asci of minus
                    {
                        Sigma_Error();
                        break;
                    }
                }
                else// its not the first digit
                {
                    if ((charArr[i] < 48 && charArr[i] != 46) || charArr[i] > 57)//if the char entered is not a number or a dot
                    {
                        Sigma_Error();
                        break;
                    }
                    if (charArr[i] == 46 && (this.sigmaDotEntered_flag == 1 || charArr[i - 1] == 45))//if its a dot but there was already entered one, or there is minus before it
                    {
                        Sigma_Error();
                        break;
                    }
                    if (charArr[i] == 46 && this.sigmaDotEntered_flag == 0 && charArr[i - 1] != 45)//case the entered char is not the first one and its a '.' but not after a minus
                        this.sigmaDotEntered_flag = 1;// a '.' was entered and so there cannot be another one
                }//else
            }//for
            if (i == sigmaStr.Length && i != 0)
            {
                this.sigma = System.Convert.ToDouble(sigmaStr);
                m_sigmaFlag = 1;
            }
        }
        
        private void Sigma_textBox_TextChanged(object sender, EventArgs e)
        {
            string sigmaStr;
            char charEnterd=new char();
            int i;
            sigmaStr = this.Sigma_textBox.Text;
            this.LengthOfSigma = sigmaStr.Length;
            if (sigmaStr != "")
            {
                charEnterd = System.Convert.ToChar(sigmaStr[LengthOfSigma - 1]);
                this.sigmaError_flag = 0;
                if (this.LengthOfSigma == 1)//if it's the first digit it cannot be a '.'
                {
                    if (charEnterd < 48 || charEnterd > 57)//'48' asci of 0 ,  '57' asci of 9,   '46' asci of . , '45' is the asci of minus
                        Sigma_Error();
                    else
                    {
                        this.charArrForSigma[LengthOfSigma - 1] = charEnterd;//update the global varibal for sigma char array
                    }
                }
                else// its not the first digit
                {
                    if ((charEnterd < 48 && charEnterd != 46) || charEnterd > 57)//if the char entered is not a number or a dot
                        Sigma_Error();
                    if (charEnterd == 46)//if its a dot
                    {
                        if (this.charArrForSigma[LengthOfSigma - 2] == 45)// but there  is minus before it
                            Sigma_Error();
                        else
                        {
                            for (i = 0; i < LengthOfSigma - 1; i++)
                            {
                                if (charArrForSigma[i] == 46)
                                {
                                    Sigma_Error();
                                    break;
                                }
                            }

                            if (i == LengthOfSigma - 1)
                            {
                                this.sigmaDotEntered_flag = 1;// a '.' was entered and so there cannot be another one
                                this.indexOfTheDot_sigma = LengthOfSigma - 1;
                            }
                        }
                    }                   
                    if (sigmaError_flag == 0)
                    {
                        this.charArrForSigma[LengthOfSigma - 1] = charEnterd;
                    }
                }
            }
            else
                this.m_sigmaFlag = 1;
        }

        public void Sigma_Error()
       {
           error.Visible = true;
           error.label1.Text = "The input is wrong !";
           error.label3.Text = "Please Enter a number.";
           error.label3.Visible = true;
           error.label2.Visible = false;
           this.sigmaError_flag = 1;
           //this.counterLengthOfSigma--;
       }

        private void sigma_finishedEntered_KeyPress(object sender, KeyPressEventArgs e)
       {
           if (e.KeyChar == 13)
               m_sigmaFlag = 1;
       }

        private void OnlineClustering_tabPage2_Leave(object sender, EventArgs e)
        {
           kernelFlag = 1;
        }

        private void KernelMatrix_comboBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 8)
                m_KernrlMatrix_flag = 0;
        }

        private void NumOfClusterKernel_comboBox_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == 8)
                m_NumOfClusterKernel_flag = 0;
        } 

        void InitializeChartAreas()
        {
            ChartArea chartArea2 = new ChartArea(), chartArea1 = new ChartArea(), chartArea3 = new ChartArea();
            chartArea2.BackImage = Directory.GetCurrentDirectory() + "\\Resources\\BackG.jpg";
            chartArea2.BorderColor = System.Drawing.Color.DimGray;
            chartArea2.CursorX.IntervalOffsetType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Number;
            chartArea2.CursorX.IntervalType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Number;
            chartArea2.Name = "ChartArea1";
            this.chart2.ChartAreas.RemoveAt(0);
            this.chart2.ChartAreas.Add(chartArea2);

            chartArea3.Area3DStyle.LightStyle = System.Windows.Forms.DataVisualization.Charting.LightStyle.Realistic;
            chartArea3.Area3DStyle.PointDepth = 50;
            chartArea3.Area3DStyle.PointGapDepth = 50;
            chartArea3.Area3DStyle.Rotation = 40;
            chartArea3.Area3DStyle.WallWidth = 2;
            chartArea3.BackImage = Directory.GetCurrentDirectory() + "\\Resources\\BackG.jpg";
            chartArea3.BackImageTransparentColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(128)))), ((int)(((byte)(0)))));
            chartArea3.BackSecondaryColor = System.Drawing.Color.Red;
            chartArea3.BorderColor = System.Drawing.Color.DimGray;
            chartArea3.CursorX.IntervalOffsetType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Number;
            chartArea3.CursorX.IntervalType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Number;
            chartArea3.Name = "ChartArea1";
            this.TotalsGraphChart.ChartAreas.RemoveAt(0);
            this.TotalsGraphChart.ChartAreas.Add(chartArea3);

            chartArea1.BackImage = Directory.GetCurrentDirectory() + "\\Resources\\BackG.jpg";
            chartArea1.BorderColor = System.Drawing.Color.DimGray;
            chartArea1.CursorX.IntervalOffsetType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Number;
            chartArea1.CursorX.IntervalType = System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType.Number;
            chartArea1.Name = "ChartArea1";
            this.InterstChart.ChartAreas.RemoveAt(0);
            this.InterstChart.ChartAreas.Add(chartArea1);
        }


        private void ClearDataFunc()
        {
            //other tab cleaning :
            Dichotom_Clustered_Flag = false;
            Graclus_Clustered_Flag = false;
            setConstants();

            this.StopingRules.Enabled = false;
            this.MinNodes.Enabled = false;
            this.MinNodesTextbox.Text = Convert.ToString(MinNodesPerCluster);
            this.MinNodesTextbox.Enabled = false;
            this.minEdges.Enabled = false;
            this.MinEdgesTextbox.Text = Convert.ToString(MinEdgesPercentPerCluster);
            this.MinEdgesTextbox.Enabled = false;
       
            this.LocalsearchlimitLabel.Visible = false;
            this.GraclusLocalSearchTextbox.Visible = false;
            this.graclusLocalSearchCheckbox.Checked = false;
            
            AutoDichotomCheck.Checked = false;
            for (int i = 0; i < CurrentNumberOfClusters; i++)
            {
                SelectBox2[i].Enabled = false;
                SelectBox2[i].Visible = false;
                NetworkInformation_groupBox.Controls.Remove(SelectBox2[i]);
            }
            //other tabs :
            this.Original_network.Visible = false;
            this.clustered_network.Visible = false;
            //clean local variables          
            this.TotalsGraphChart.Visible=false;
            this.chart2.Visible = false;
            this.InterstChart.Visible = false;
            this.Network_number.Text = " ";
            this.Number_of_clusters.Text = " ";
            this.Number_of_nodes_in_network.Text = " ";
            this.avgK_klik.Text = " ";
            this.Network_number_results.Text = " ";
            this.NumOfNodes_Results.Text = " ";
            this.InterstChart.Series.Clear();            
            this.chart2.Series.Clear();            
            // init 2nd tab kernel gui and prefs
            kernelFlag = 1;
            this.ReClusterButton.Enabled = true;
            this.Run_K_Means_button.Enabled = true;
            this.Dichotom_button.Enabled = true;
            this.graclusRunButton.Enabled = true;
            this.m_gImage3.Clear(Color.Transparent);    // prep img for 2nd tab
            this.m_gImage3_Graclus.Clear(Color.Transparent);    // prep img for 2nd tab
            this.dataGridView1.Rows.Clear();        // clean results table
            this.K_Means_progressBar.Value = K_Means_progressBar.Minimum;
            this.graclus_progressBar.Value= this.graclus_progressBar.Minimum;

            this.m_KernrlMatrix_flag = 1;
            this.m_NumOfClusterKernel_flag = 1;
            this.m_sigmaFlag = 1;
            this.Sigma_textBox.Clear();
           
            this.KernelMatrix_comboBox.Enabled = true;
            //this.NumOfClusterKernel_comboBox.Enabled = true;
            this.Sigma_textBox.Enabled = true;
            this.NetworkInformation_groupBox.Visible = false;
            this.ConvertNetwork_Button.Enabled = false;

            this.GraclusLocalSearchTextbox.Text = Convert.ToString(MinLocalSearchDefault);
            this.GraclusLocalSearchTextbox.Text = Convert.ToString(MinLocalSearchDefault);
            this.MinNodesTextbox.Text = Convert.ToString(MinNodesPerCluster);
            this.MinEdgesTextbox.Text = Convert.ToString(MinEdgesPercentPerCluster);
            this.Sigma_textBox.Text = Convert.ToString(DefaultSigma);
            this.KernelMatrix_comboBox.SelectedItem = DefaultKernelMatrix;
            this.graclusKernelCombobox.SelectedItem = DefaultKernelMatrix;
            this.graclusClusternumCombobox.SelectedIndex = (MaxClustersRequested-1);
            //this.NumOfClusterKernel_comboBox.SelectedIndex = (MaxClustersRequested - 1);
            this.Graclus_Clustering_panel.Visible = false;
            this.Clear_data.Enabled = false;            
        }
                
        void GetAnalyzedResults(Kernel_K_Means KMeans, int NumOfClusters, Boolean FromGraclus)
        {   /*  ClusterData[]: 0: Cluster#                    4: Users# with memberOf 
             *                 1: Users# with interests       5: Users# with 1st memberOf  
             *                 2: Users# with 1st interest    6: memberOfTXT
             *                 3: InterestTXT                                          */
            String CurrentAlg="-Dichotom.txt",line;
            if (FromGraclus)
                CurrentAlg = "-Graclus.txt";
            int NetworkNumber = m_currentNetworkIndex,CurCluster=-1;           
            try
            {
                string temp = "Networks\\" + NetworkNumber + "-Analyze" + NumOfClusters + CurrentAlg;
                using (StreamReader sr = new StreamReader(temp))
                {
                    while ((line = sr.ReadLine()) != null)//|| UserIndex <= Temp_K_Means.ClusterNode.Length)
                    {
                        String[] ClusterData = line.Split('-');
                        CurCluster=Convert.ToInt32(ClusterData[0]);
                        KMeans.ClusterArray[CurCluster].numOfUsersWithInterests = Convert.ToInt32(ClusterData[1]);
                        KMeans.ClusterArray[CurCluster].numOfUsers1stInterests = Convert.ToInt32(ClusterData[2]);
                        KMeans.ClusterArray[CurCluster].Interests1st = ClusterData[3];
                        KMeans.ClusterArray[CurCluster].numOfUsersWithMemberOf = Convert.ToInt32(ClusterData[4]);
                        KMeans.ClusterArray[CurCluster].numOfUsers1stMemberOf = Convert.ToInt32(ClusterData[5]);
                        KMeans.ClusterArray[CurCluster].MemberOf1st = ClusterData[6];
                    }
                    KMeans.InterestsExists = true;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("The file could not be read:");
                Console.WriteLine(e.Message);
            }

        }


        // if clicked the labe "view graph" (2nd tab) it call the picture handler
        private void ViewGraph_Click(object sender, EventArgs e)
        { 
            pictureBox2_Click(sender, e);
        }

        private void MinNodesTextbox_TextChanged(object sender, EventArgs e)
        {
            if(MinNodesTextbox.Text != "")
            MinNodesPerCluster = Convert.ToInt32(MinNodesTextbox.Text);
        }

        private void MinEdgesTextbox_TextChanged(object sender, EventArgs e)
        {
            if (MinEdgesTextbox.Text != "")
                MinEdgesPercentPerCluster = Convert.ToInt32(MinEdgesTextbox.Text);
        }

        private void DichotomRadiobutton_CheckedChanged(object sender, EventArgs e)
        {
            if (DichotomRadiobutton.Checked)
            {
                GraclusRadiobutton.Checked = false;
                graclusgroupbox4.Visible = false;
                this.Graclus_Clustering_panel.Visible = false;
                Graclus_NetworkInformation_groupBox.Visible = false;

                groupBox4.Visible = true;
                if (Dichotom_Clustered_Flag)
                {
                    NetworkInformation_groupBox.Visible = true;
                    Online_Clustering_panel.Visible = true;
                }
            }
        }

        private void GraclusRadiobutton_CheckedChanged(object sender, EventArgs e)
        {
            if (GraclusRadiobutton.Checked)
            {
                DichotomRadiobutton.Checked = false;
                groupBox4.Visible = false;                              
                Online_Clustering_panel.Visible = false;
                NetworkInformation_groupBox.Visible = false;

                graclusgroupbox4.Visible = true;
                if (Graclus_Clustered_Flag)
                {
                    Graclus_NetworkInformation_groupBox.Visible = true;
                    this.Graclus_Clustering_panel.Visible = true;
                }
            }

        }

        private void graclusLocalSearchCheckbox_CheckedChanged(object sender, EventArgs e)
        {
            this.LocalsearchlimitLabel.Visible = graclusLocalSearchCheckbox.Checked;
            this.GraclusLocalSearchTextbox.Visible = graclusLocalSearchCheckbox.Checked;
        }

        private void Clear_data_Click_1(object sender, EventArgs e)
        {
            ClearDataFunc();
        }

        private void Graclus_pictureBox2_Click(object sender, EventArgs e)
        {
            if (GraphGraclus != null)
                this.GraphGraclus.Dispose();
            this.GraphGraclus = new Average_graph();
            FillGraph(ref this.GraphGraclus.chart1); // 2nd tab graph
            this.GraphGraclus.Visible=true;
        }

        private void Graclus_ExportResults_Click(object sender, EventArgs e)
        {
            ExportResultsToTXT(Graclus_K_Means, GraclusNumOfClusters, true);  
            CMDAnalyzer();
            GetAnalyzedResults(Graclus_K_Means, GraclusNumOfClusters, true);
            FillTable(ref Graclus_dataGridView1, Graclus_K_Means, GraclusNumOfClusters, true);
            Draw_Clusterd_Kernel(m_gImage3_Graclus, Graclus_K_Means, GraclusNumOfClusters, true);
            FillInterestGraph(ref InterstChart); 
            Graclus_NetworkInformation_groupBox.Refresh();
            Online_Clustering_groupBox.Refresh();
            this.Graclus_Clustering_panel.Refresh();           
             
        }

        private void ExportResults_Click(object sender, EventArgs e)
        {
            ExportResultsToTXT(m_Kernel_K_Means, CurrentNumberOfClusters, false);
            CMDAnalyzer();
            GetAnalyzedResults(m_Kernel_K_Means, CurrentNumberOfClusters, false);
            FillTable(ref dataGridView1, m_Kernel_K_Means, CurrentNumberOfClusters, false);
            Draw_Clusterd_Kernel(m_gImage3, m_Kernel_K_Means, CurrentNumberOfClusters, false);
            FillInterestGraph(ref InterstChart); 
            Graclus_NetworkInformation_groupBox.Refresh();
            Online_Clustering_groupBox.Refresh();
            this.Graclus_Clustering_panel.Refresh();
        }
    }
}